home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 …ember: Reference Library / Dev.CD Dec 00 RL Disk 1.toast / pc / technical documentation / develop / develop issue 27 / develop issue 27 code / 3d game controls / source / gamecontrols.c < prev    next >
Encoding:
Text File  |  1996-06-29  |  9.5 KB  |  285 lines

  1. //--------------------------------------------------------------------------------------------
  2. //  Game Controller Code
  3. //
  4. //      by Philip McBride
  5. //
  6. //--------------------------------------------------------------------------------------------
  7.  
  8.  
  9. #include <FixMath.h>
  10. #include "GameControls.h"
  11. #include "extern.h"
  12. #include "camera.h"
  13. #include "document.h"
  14. #include "draw.h"
  15.  
  16. //--------------------------------------------------------------------------------------------
  17. //  Initialize Delta Factors
  18. //
  19. void MyInitDeltaFactors(DocumentPtr theDocument)
  20. {
  21.     TQ3BoundingBox         viewBBox;
  22.     TQ3Vector3D            diagonalVector;
  23.     float                maxDimension;
  24.  
  25.     // Get the bounding box and find the scene dimension.
  26.     MyGetBoundingBox(theDocument, theDocument->documentGroup, &viewBBox);
  27.     Q3Point3D_Subtract(&viewBBox.max, &viewBBox.min, &diagonalVector);
  28.     maxDimension = Q3Vector3D_Length(&diagonalVector);
  29.  
  30.     // Now set the delta factors.  Note, using the maxDimension
  31.     // for the rotation factors works for some size models, but
  32.     // you will need a more complex multipler to handle any size
  33.     // model.  Some multiplier that allows the maxDimension to
  34.     // only have a little effect on the rotation factors.  Some
  35.     // experimentation is needed here.
  36.     theDocument->xRotFactor = kXRotFactorBase * maxDimension;
  37.     theDocument->yRotFactor = kYRotFactorBase * maxDimension;
  38.     theDocument->zRotFactor = kZRotFactorBase * maxDimension;
  39.     theDocument->xMoveFactor = kXMoveFactorBase * maxDimension;
  40.     theDocument->yMoveFactor = kYMoveFactorBase * maxDimension;
  41.     theDocument->zMoveFactor = kZMoveFactorBase * maxDimension;
  42.  
  43.     // Set up the control factor.
  44.     theDocument->controlFactor = kControlFactorBase * maxDimension;
  45. }
  46.  
  47. //--------------------------------------------------------------------------------------------
  48. //  Handle Mouse Moves
  49. //
  50. void MyDoMouseMove(WindowPtr theWindow, EventRecord *theEvent)
  51. {
  52.     DocumentPtr            theDocument;
  53.     Point                 newMouse;
  54.     long                dx, dy, oldX, oldY;
  55.     float                xRot, yRot;
  56.     short                usingControl = false;
  57.     
  58.     // Get the document from the window.
  59.     theDocument = MyGetDocumentFromWindow(theWindow);
  60.  
  61.     // Get the current mouse position.
  62.     GetMouse(&newMouse);        
  63.     oldX = newMouse.h;
  64.     oldY = newMouse.v;
  65.  
  66.     // If the control key is down, then we're in depth mode.
  67.     if (theEvent->modifiers & controlKey)
  68.         usingControl = true;
  69.  
  70.     // Loop, moving the camera while you have the mouse down.
  71.     while (StillDown()) {
  72.         // Get the next mouse position.
  73.         GetMouse(&newMouse);
  74.  
  75.         // Calculate the difference from the last mouse position.
  76.         dx = newMouse.h - oldX;
  77.         dy = oldY - newMouse.v;
  78.         
  79.         // If there's some difference, move the camera.
  80.         if ((dx != 0) || (dy != 0)) {
  81.             // Calculate the rotation about the y axis (pan) and rotate.
  82.             yRot = ((float) dx * (kQ3Pi / 180.0)) / theDocument->width;
  83.             MyRotateCameraY(theDocument, -yRot * theDocument->yRotFactor);
  84.  
  85.             // If the control key is down, move along the z axis;
  86.             // otherwise, rotate about the x axis
  87.             if (usingControl) {
  88.                 // Move the camera along the z axis (change in mouse's y).
  89.                 MyMoveCameraZ(theDocument, dy * theDocument->zMoveFactor);
  90.             } else {
  91.                 // Calculate the rotation about the x axis (pitch) and rotate.
  92.                 xRot = ((float) dy * (kQ3Pi / 180.0)) / theDocument->height;
  93.                 MyRotateCameraX(theDocument, xRot * theDocument->xRotFactor);
  94.             }
  95.             // Update the screen for each move.
  96.             MyUpdateScreen(theDocument);
  97.         }
  98.         // Set the current mouse position as the old mouse position for the next update.
  99.         oldX = newMouse.h;
  100.         oldY = newMouse.v;
  101.     }
  102. }
  103.  
  104. //--------------------------------------------------------------------------------------------
  105. //  Check for Key
  106. //
  107. // Key checking code taken directly from "Tricks of the Mac Game Programming Gurus"
  108. // from chapter 5 "User Interaction."  As noted in that book, since we are calling
  109. // this for each key we are interested in, this is not the best way to handle that
  110. // for effeciency.  Better would be to call the getkeys once and test for all the
  111. // keys of interest.
  112. Boolean CheckKey(short keyCode)
  113. {
  114.     KeyMap    myKeyMap;
  115.     short    byteIndex;
  116.     char    theByte, theBit;
  117.     char    *thePointer;
  118.  
  119.     GetKeys(myKeyMap);
  120.     byteIndex = keyCode >> 3;
  121.     thePointer = (char *)&myKeyMap[0];
  122.     theByte = *(char *)(thePointer + byteIndex);
  123.     theBit = 1L<<(keyCode & 7);
  124.     return ( (theByte & theBit) != 0 );
  125. }
  126.  
  127. //--------------------------------------------------------------------------------------------
  128. //  Handle Keyboard Moves
  129. //
  130. void MyDoKeyMove(WindowPtr theWindow, EventRecord *theEvent, char theKey)
  131. {
  132.     float                step = 10.0;  // Arbitrary stepper for mouse/key differences
  133.     DocumentPtr            theDocument = MyGetDocumentFromWindow(theWindow);
  134.     Boolean                moveHappened;
  135.  
  136.     theKey = theKey;
  137.     theEvent = theEvent;
  138.             
  139.     // This while loop is not very nice to any other applications
  140.     // out there.  It will stay in a loop until a mouse button is
  141.     // hit.  This is fine for games that really take over the mac,
  142.     // but in general it would be nicer to allow many other things
  143.     // to interrupt as well as just generally giving some idle time
  144.     // back.
  145.     while (!Button()) {
  146.         moveHappened = false;
  147.         
  148.         // For each key of interest, check and do a move.
  149.         if (CheckKey(iRight)) {
  150.             MyMoveCameraX(theDocument, step * theDocument->xMoveFactor);
  151.             moveHappened = true;
  152.         }
  153.         if (CheckKey(iLeft)) {
  154.             MyMoveCameraX(theDocument, -step * theDocument->xMoveFactor);
  155.             moveHappened = true;
  156.         }
  157.         if (CheckKey(iUp)) {
  158.             MyMoveCameraY(theDocument, step * theDocument->yMoveFactor);
  159.             moveHappened = true;
  160.         }
  161.         if (CheckKey(iDown)) {
  162.             MyMoveCameraY(theDocument, -step * theDocument->yMoveFactor);
  163.             moveHappened = true;
  164.         }
  165.         if ((CheckKey(iUpArrow)) || (CheckKey(iForward))) {
  166.             MyMoveCameraZ(theDocument, step * theDocument->zMoveFactor);
  167.             moveHappened = true;
  168.         }
  169.         if ((CheckKey(iDownArrow)) || (CheckKey(iBackward))) {
  170.             MyMoveCameraZ(theDocument, -step * theDocument->zMoveFactor);
  171.             moveHappened = true;
  172.         }
  173.         if (CheckKey(iPanUp)) {
  174.             MyRotateCameraX(theDocument, (kQ3Pi/180.0)  * (1.0 / step) * theDocument->xRotFactor);
  175.             moveHappened = true;
  176.         }
  177.         if (CheckKey(iPanDown)) {
  178.             MyRotateCameraX(theDocument, (-kQ3Pi/180.0) * (1.0 / step) * theDocument->xRotFactor);
  179.             moveHappened = true;
  180.         }
  181.         if ((CheckKey(iRightArrow)) || (CheckKey(iPanRight))) {
  182.             MyRotateCameraY(theDocument, (-kQ3Pi/180.0) * (1.0 / step) * theDocument->yRotFactor);
  183.             moveHappened = true;
  184.         }
  185.         if ((CheckKey(iLeftArrow)) || (CheckKey(iPanLeft))) {
  186.             MyRotateCameraY(theDocument, (kQ3Pi/180.0) * (1.0 / step) * theDocument->yRotFactor);
  187.             moveHappened = true;
  188.         }
  189.         if (CheckKey(iBankL)) {
  190.             MyRotateCameraZ(theDocument, (-kQ3Pi/180.0) * theDocument->zRotFactor);
  191.             moveHappened = true;
  192.         }
  193.         if (CheckKey(iBankR)) {
  194.             MyRotateCameraZ(theDocument, (kQ3Pi/180.0) * theDocument->zRotFactor);
  195.             moveHappened = true;
  196.         }
  197.         
  198.         // Now update the screen after a move
  199.         if (moveHappened)
  200.             MyUpdateScreen(theDocument);
  201.     }
  202. }
  203.  
  204. /*
  205. // This is an alternative MyDoKeyMove that makes each keyboard move during
  206. // the event loop.  Thus being nice to the rest of the mac and any other
  207. // applications out there.  Of course, this won't move as smooth as the
  208. // above version   Note for this version, you would use the char codes
  209. // for the keys instead of the numbers (see the enum with iRight, etc.
  210. // in GameControls.h).
  211. void MyDoKeyMove(WindowPtr theWindow, EventRecord *theEvent, char theKey)
  212. {
  213.     float                step;
  214.     DocumentPtr            theDocument = MyGetDocumentFromWindow(theWindow);
  215.         
  216.     // Some arbitrary stepping values for the modifier keys (and for handling
  217.     // the difference between keyboard and mouse)
  218.     step = 10.0;
  219.     if (theEvent->modifiers & shiftKey) step = 0.1;
  220.     if (theEvent->modifiers & controlKey) step = 1.0;
  221.     if (theEvent->modifiers & optionKey) step = 20.0;
  222.     
  223.     // This handles only one key at a time.  To handle multiple keys
  224.     // you need to use GetKeys to get all the keys down (that you are
  225.     // interested in) and then instead of a switch, check for each
  226.     // key of interest (with if statements).
  227.     switch(theKey)
  228.         {
  229.         case iRight:
  230.             MyMoveCameraX(theDocument, step * theDocument->xMoveFactor);
  231.             MyUpdateScreen(theDocument);
  232.             break;
  233.         case iLeft:
  234.             MyMoveCameraX(theDocument, -step * theDocument->xMoveFactor);
  235.             MyUpdateScreen(theDocument);
  236.             break;
  237.         case iUp:
  238.             MyMoveCameraY(theDocument, step * theDocument->yMoveFactor);
  239.             MyUpdateScreen(theDocument);
  240.             break;
  241.         case iDown:
  242.             MyMoveCameraY(theDocument, -step * theDocument->yMoveFactor);
  243.             MyUpdateScreen(theDocument);
  244.             break;
  245.         case iUpArrow:
  246.         case iForward:
  247.             MyMoveCameraZ(theDocument, step * theDocument->zMoveFactor);
  248.             MyUpdateScreen(theDocument);
  249.             break;
  250.         case iDownArrow:
  251.         case iBackward:
  252.             MyMoveCameraZ(theDocument, -step * theDocument->zMoveFactor);
  253.             MyUpdateScreen(theDocument);
  254.             break;
  255.         case iPanUp:
  256.             MyRotateCameraX(theDocument, (kQ3Pi/180.0)  * (1.0 / step) * theDocument->xRotFactor);
  257.             MyUpdateScreen(theDocument);
  258.             break;
  259.         case iPanDown:
  260.             MyRotateCameraX(theDocument, (-kQ3Pi/180.0) * (1.0 / step) * theDocument->xRotFactor);
  261.             MyUpdateScreen(theDocument);
  262.             break;
  263.         case iRightArrow:
  264.         case iPanRight:
  265.             MyRotateCameraY(theDocument, (-kQ3Pi/180.0) * (1.0 / step) * theDocument->yRotFactor);
  266.             MyUpdateScreen(theDocument);
  267.             break;
  268.         case iLeftArrow:
  269.         case iPanLeft:
  270.             MyRotateCameraY(theDocument, (kQ3Pi/180.0) * (1.0 / step) * theDocument->yRotFactor);
  271.             MyUpdateScreen(theDocument);
  272.             break;
  273.         case iBankL:
  274.             MyRotateCameraZ(theDocument, (-kQ3Pi/180.0) * theDocument->zRotFactor);
  275.             MyUpdateScreen(theDocument);
  276.             break;
  277.         case iBankR:
  278.             MyRotateCameraZ(theDocument, (kQ3Pi/180.0) * theDocument->zRotFactor);
  279.             MyUpdateScreen(theDocument);
  280.             break;
  281.         default:
  282.             break;
  283.         }
  284. }
  285. */